#ifndef xpack_interface_seqptr
#define xpack_interface_seqptr
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::interface_seqptr::inc
#include"adapter/random_access.hpp"
#include"define/base_type.hpp"
#include"define/classify.hpp"
#include"interface/initializer_list.hpp"
#include"macro/xexport.hpp"
#include"macro/xstruct.hpp"
#include"macro/xunlikely.hpp"
#include"meta/has_cast.hpp"
#include"meta/has_operator_cast.hpp"
#include"math/index_system.hpp"
#include"meta/is_initializer_listx.hpp"
#include"meta/is_origin_arrayx.hpp"
#include"meta/is_origin_stringx.hpp"
#include"meta/is_the_xstruct.hpp"
#include"meta/item_of.hpp"
#include"meta/remove_ref.hpp"
#pragma pop_macro("xuser")

namespace mixc::interface_seqptr{
    template<class seq_t>
    concept has_length = requires(seq_t seq, uxx length){
        length  = seq->length;
    };

    template<class seq_t, class item_t>
    concept has_ptr_length_pairx = 
        has_length<seq_t> and (inc::has_cast<item_t *, seq_t> or inc::has_operator_cast<item_t *, seq_t>);

    template<class item_type>
    xstruct(
        xtmpl(seqptr, item_type),
        xpubb(inc::random_access<seqptr<item_type>, item_type>),
        xprif(m_ptr,  item_type *),
        xprif(m_len,  uxx),
        xwhos(inc::classify_t::interface_seqptr)
    )
    public:
        using item_t            = item_type;
        using final_t           = the_t;
    public:
        xprops()
            xpubgetx(length, uxx){
                xr{ return xthe.m_len; }
            };

            xpubgetx(is_support_logic_inverse, bool){
                xr{ return false; }
            };
        $

        xprops_operator()

    public:
        constexpr seqptr() : 
            m_ptr(nullptr), m_len(0){}

        template<class seq_t>
        requires(
            inc::is_origin_arrayx<seq_t, item_t> and not inc::is_origin_stringx<seq_t, item_t>
        )
        constexpr seqptr(seq_t && ary) : 
            seqptr(ary, sizeof(seq_t) / sizeof(ary[0])){}

        template<class seq_t>
        requires(inc::is_origin_stringx<seq_t, item_t>)
        constexpr seqptr(seq_t && list) : 
            seqptr(list, ([&](){
                uxx i = 0;
                while(list[i] != '\0'){
                    i++;
                }
                return i;
            })()){
        }

        constexpr seqptr(item_t const * ptr, uxx len) : 
            m_ptr((item_t *)ptr), m_len(len){}

        constexpr seqptr(inc::initializer_list<item_t> const & seq) :
            seqptr(seq.begin(), seq.size()){
        }

        template<class seq_t>
        requires(has_ptr_length_pairx<seq_t, item_t>)
        constexpr seqptr(seq_t const & list) : 
            seqptr((item_t const *)list, list->length){
        }

        template<class seq_t>
        requires(has_ptr_length_pairx<seq_t, item_t>)
        constexpr seqptr(seq_t const & list, uxx length) : 
            seqptr((item_t const *)(seq_t &)list, length){
        }

        operator item_t *(){
            return m_ptr;
        }

        operator item_t const *() const{
            return m_ptr;
        }

        final_t backward(uxx offset) const {
            return the_t(m_ptr + offset, m_len - offset);
        }

        final_t forward(uxx offset) const {
            return the_t(m_ptr - offset, m_len + offset);
        }

        template<can_interval interval_t>
        final_t subseq(interval_t const & i) const {
            xunlikely(i.normalize(xthe->length) == bstate_t::fail){
                return the_t(m_ptr + i->left, 0);
            }
            return the_t(m_ptr + i->left, i->right - i->left + 1);
        }
    
    private:
        friend inc::random_access<the_t, item_type>;

        item_t & random_get(uxx index) const {
            return m_ptr[index];
        }
    $

    template<class seq_t, class item_t>
    concept can_seqptrlizex = requires(seq_t && seq){
        seqptr<item_t>(seq);
    };

    template<class seq_t>
    concept can_seqptrlize = 
        can_seqptrlizex<
            seq_t, 

            // 不能是 inc::item_origin_of<seq_t> 比如元素类型是 asciis 就会移除 const 标记
            inc::remove_ref<inc::item_of<seq_t>>
        >;
}

namespace mixc::interface_seqptr::origin{
    using mixc::interface_seqptr::can_seqptrlize;
    using mixc::interface_seqptr::can_seqptrlizex;
    using mixc::interface_seqptr::seqptr;
}

#endif

xexport_space(mixc::interface_seqptr::origin)